﻿////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  © 2012 Stanislav S. Yarmonov.
//
//  TODO:LICENSE
//     
////////////////////////////////////////////////////////////////////////////////////////////////////
using System;

namespace Pandora.Development.Parser
{
    public class BaseInput<TToken> : IParseInput<TToken>
    {
        private class Failure<TResult> : IParseFailure<TToken, TResult>
        {
            private IParseError _Error = null;
            public IParseError Error
            {
                get
                {
                    return _Error;
                }
            }

            public Failure(IParseError error)
            {
                _Error = error;
            }
        }

        private class Success<TResult> : IParseSuccess<TToken, TResult>
        {
            private BaseInput<TToken> _Input = null;

            private TResult _Result = default(TResult);
            public TResult Result
            {
                get
                {
                    return _Result;
                }
            }

            private IParseInput<TToken> _Remains = null;
            public IParseInput<TToken> Remains
            {
                get
                {
                    if (_Remains == null)
                    {
                        _Remains = new BaseInput<TToken>(_Input._Buffer, _Input._Position + 1);
                    }

                    return _Remains;
                }
            }

            public Success(BaseInput<TToken> input, TResult result, bool next)
            {
                _Result = result;
                _Input = input;
                if (!next)
                {
                    _Remains = _Input;
                }
            }
        }

        private TToken[] _Buffer = null;
        private int _Position = 0;

        public TToken Current
        {
            get
            {
                //TODO:throw exception if !(_Position < _Buffer.Length)
                return _Buffer[_Position];
            }
        }

        public bool CanRead
        {
            get
            {
                return _Position < _Buffer.Length;
            }
        }

        public IParseSuccess<TToken, TResult> CreateSuccess<TResult>(TResult result, bool next = false)
        {
            return new BaseInput<TToken>.Success<TResult>(this, result, next);
        }

        public IParseFailure<TToken, TResult> CreateFailure<TResult>(IParseError error)
        {
            return new BaseInput<TToken>.Failure<TResult>(error);
        }

        private BaseInput(TToken[] tokens, int position)
        {
            _Position = position;
            _Buffer = tokens;
        }

        public BaseInput(TToken[] tokens)
        {
            //TODO:Check tokens arguments for null
            _Position = 0;
            _Buffer = tokens;
        }
    }
}
